package com.example.concurrent.chapter18;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @author Create By Liuqz
 * @date 2018/11/27 11:49
 *
 * 不可变累加器对象设计
 */
//不可变对象不允许被继承
public final class immutableIntegerAccumulator {

    private final int init;

    //构造时传入初始值
    public immutableIntegerAccumulator(int init) {
        this.init = init;
    }

    //构造新的累加器,需要用到另外一个accumulator和初始值
    public immutableIntegerAccumulator(immutableIntegerAccumulator accumulator, int init) {
        this.init = accumulator.getValue() + init;
    }

    //每次相加都会产生一个新的immutableIntegerAccumulator
    public immutableIntegerAccumulator add(int i) {
        return new immutableIntegerAccumulator(this, i);
    }

    public int getValue() {
        return this.init;
    }


    /**
     * 重构后,使用final修饰其的目的是为了防止由于继承重写而导致失去线程安全性,
     * 另外init属性被final修饰不允许线程对其进行改变,在构造函数中赋值后将不会改变
     *
     * @param args
     */
    public static void main(String[] args) {
        //同样的方式进行测试
        immutableIntegerAccumulator accumulator = new immutableIntegerAccumulator(0);
        IntStream.range(0,3).forEach(i -> new Thread(() -> {
            int inc = 0;
            while (true) {
                int oldValue = accumulator.getValue();
                int result = accumulator.add(inc).getValue();
                System.out.println(oldValue + " + " + inc + " = " + result);
                if (oldValue + inc != result) {
                    System.err.println("ERROR : " + oldValue + " + " + inc + " = " + result);
                }
                inc++;
                showly();
            }
        }).start());
    }

    private static void showly() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
